package smecta.client.print.service.print;

import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.printing.PDFPageable;
import org.jxls.builder.JxlsOutputFile;
import org.jxls.transform.poi.JxlsPoiTemplateFillerBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import smecta.client.print.common.exceptions.ServiceException;
import smecta.client.print.domain.PTInputContext;
import smecta.client.print.domain.PTRuntimeContext;
import smecta.client.print.service.file.FileTypeConvertService;

import javax.print.PrintServiceLookup;
import java.awt.print.PrinterJob;
import java.io.File;
import java.util.UUID;

@Slf4j
@Service
public class PrintServiceImpl implements PrintService{

    @Autowired
    private FileTypeConvertService fileTypeConvertService;

    public void print(PTInputContext context) {
        PTRuntimeContext runtimeContext = initRuntimeContext(context);
        stepGenExcel(runtimeContext);
        stepGenPDF(runtimeContext);
        stepSendToPrint(runtimeContext);
        stepClearTempData(runtimeContext);
    }

    private PTRuntimeContext initRuntimeContext(PTInputContext context) {
        PTRuntimeContext runtimeContext = new PTRuntimeContext();
        runtimeContext.setPrinterName(context.getPrinterName());
        runtimeContext.setTemplatePath(context.getTemplatePath());
        runtimeContext.setTemplateData(context.getTemplateData());
        return runtimeContext;
    }

    // 两种实现方式:1.使用easypoi[国内优秀] 2.使用jxls[国外优秀]
    private String stepGenExcel(PTRuntimeContext context) {
        String outputPath = System.getProperty("user.dir") + System.getProperty("file.separator") + String.format("%s-%s-scp.xlsx", UUID.randomUUID().toString(), System.currentTimeMillis());
        try {
            // 使用 JxlsPoiTemplateFillerBuilder 进行数据填充
            JxlsPoiTemplateFillerBuilder.newInstance()
                    .withTemplate(context.getTemplatePath())
                    .build()
                    .fill(context.getTemplateData(), new JxlsOutputFile(new File(outputPath)));
            log.info("PrintService stepGenExcel success:{}", outputPath);
        } catch (Exception e) {
            log.error("PrintService stepGenExcel error:{}", e);
            throw new ServiceException(e.getMessage());
        }
        context.setXlsxFilePath(outputPath);
        return outputPath;
    }


    private String stepGenPDF(PTRuntimeContext context) {
        String outputPath = System.getProperty("user.dir") + System.getProperty("file.separator") + String.format("%s-%s-scp.pdf", UUID.randomUUID().toString(), System.currentTimeMillis());
        try {
            fileTypeConvertService.convertToPDF(context.getXlsxFilePath(), outputPath);
            log.info("PrintService stepGenPDF success:{}", outputPath);
        } catch (Exception e) {
            log.error("PrintService stepGenPDF error:{}", e);
        }
        context.setPdfFilePath(outputPath);
        return outputPath;
    }

    private void stepSendToPrint(PTRuntimeContext context) {
        try {
            File pdfFile = new File(context.getPdfFilePath());
            PDDocument document = PDDocument.load(pdfFile);
            javax.print.PrintService printService = findPrintService(context.getPrinterName());
            if (printService == null) {
                throw new IllegalArgumentException("Printer not found: " + context.getPrinterName());
            }
            PrinterJob job = PrinterJob.getPrinterJob();
            job.setPageable(new PDFPageable(document));
            job.setPrintService(printService);
            job.print();
            document.close();
        } catch (Exception e) {
            log.error("stepSendToPrint error: {}", e);
            throw new ServiceException(e.getMessage());
        }
    }

    private void stepClearTempData(PTRuntimeContext context) {
        try {
            new File(context.getXlsxFilePath()).delete();
        } catch (Exception e) {
            log.error("stepClearTempData error: {}", e);
        }
        try {
            new File(context.getPdfFilePath()).delete();
        } catch (Exception e) {
            log.error("stepClearTempData error: {}", e);
        }
    }

    private static javax.print.PrintService findPrintService(String printerName) {
        javax.print.PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null);
        for (javax.print.PrintService printService : printServices) {
            if (printService.toString().contains(printerName)) {
                return printService;
            }
        }
        return null;
    }
}
